
export class DirTree {
    public name: string;
    public parent?: DirTree;
    subDirs: { [name: string]: DirTree };
    subFiles: string[];


    constructor(name: string, parent?: DirTree) {
        this.name = name;
        this.parent = parent;
        this.subDirs = {};
        this.subFiles = [];
    }

    public addDir(dir: string): DirTree {
        if (this.subDirs[dir]) {
            return this.subDirs[dir];
        };
        this.subDirs[dir] = new DirTree(dir, this);
        return this.subDirs[dir];
    }

    public addFile(file: string) {
        file = file.replace(new RegExp("\\\\", 'g'), "/");
        this.checkAddFile(file);
    }

    public get deep() {
        let deep = this.name;
        if (this.parent) {
            deep = this.parent?.deep + '/' + deep;
        }
        return deep;
    }

    protected checkAddFile(file: string) {
        let index = file.indexOf('/');
        if (index != -1) {
            let dirName = file.substring(0, index);
            let dir = this.addDir(dirName);
            dir?.checkAddFile(file.substr(index + 1));
        } else {
            if (this.subFiles.indexOf(file) == -1) {
                this.subFiles.push(file);
            }
        }
    }

    public toString() {
        let str = this.deep + '\n';
        str += JSON.stringify(this.subFiles, null, 4) + '\n';
        let subDirs = Object.keys(this.subDirs);
        for (let i = 0; i < subDirs.length; i++) {
            str += this.subDirs[subDirs[i]].toString();
        }
        return str;
    }

    public forEachFile(fileCb: { (file: string, dir: DirTree): void }) {
        this.subFiles.forEach((file: string, idnex: number) => {
            fileCb(file, this);
        })
        let dirs = Object.keys(this.subDirs);
        dirs.forEach((dirName: string, index: number) => {
            this.subDirs[dirName].forEachFile(fileCb);
        })
    }

}